/*            Copyright(c) 2006-2008 Dave Sexton           *
 * http://www.codeplex.com/DocProject                      *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Xml.XPath;
using System.ComponentModel.Design;
using System.Windows.Forms.Design;

namespace DaveSexton.DocProject.Sandcastle.BuildComponents.TypeConverters.BuiltIn
{
	internal sealed class SyntaxComponentTypeConverter : TypeConverter
	{
		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="SyntaxComponentTypeConverter" /> class.
		/// </summary>
		public SyntaxComponentTypeConverter()
		{
		}
		#endregion

		#region Methods
		private static IEnumerable<IXPathNavigable> GetGenerators(IXPathNavigable navigable)
		{
			if (navigable != null)
			{
				XPathNavigator navigator = navigable.CreateNavigator();

				if (navigator.MoveToChild("generators", ""))
				{
					foreach (XPathNavigator node in navigator.SelectChildren("generator", ""))
						yield return node.CreateNavigator();
				}
			}
		}

		public override bool GetPropertiesSupported(ITypeDescriptorContext context)
		{
			return true;
		}

		public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
		{
			PropertyDescriptorCollection properties = new PropertyDescriptorCollection(null);

			int i = 0;
			foreach (IXPathNavigable generator in GetGenerators(value as IXPathNavigable))
				properties.Add(new GeneratorPropertyDescriptor("Generator" + i++, generator, context));

			return properties;
		}

		public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
		{
			if (destinationType == typeof(string))
			{
				List<IXPathNavigable> generators = new List<IXPathNavigable>(GetGenerators(value as IXPathNavigable));

				return string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Text.SyntaxComponentValue, generators.Count);
			}
			else
				return base.ConvertTo(context, culture, value, destinationType);
		}
		#endregion

		#region Nested
		private sealed class GeneratorPropertyDescriptor : PropertyDescriptor
		{
			#region Public Properties
			public override Type ComponentType
			{
				get
				{
					return context.PropertyDescriptor.ComponentType;
				}
			}

			public override bool IsReadOnly
			{
				get
				{
					return true;
				}
			}

			public override Type PropertyType
			{
				get
				{
					return typeof(string);
				}
			}

			public override string DisplayName
			{
				get
				{
					return displayName;
				}
			}

			public override string Description
			{
				get
				{
					return string.Format(System.Globalization.CultureInfo.CurrentCulture,
						Resources.Text.SyntaxComponentGeneratorDescription, 
						generator.GetAttribute("type", ""), Environment.NewLine, generator.GetAttribute("assembly", ""));
				}
			}
			#endregion

			#region Private / Protected
			private readonly XPathNavigator generator;
			private readonly string displayName;
			private readonly ITypeDescriptorContext context;
			#endregion

			#region Constructors
			/// <summary>
			/// Constructs a new instance of the <see cref="GeneratorPropertyDescriptor" /> class.
			/// </summary>
			public GeneratorPropertyDescriptor(string name, IXPathNavigable generator, ITypeDescriptorContext context)
				: base(name, new Attribute[] { new NotifyParentPropertyAttribute(true) })
			{
				this.generator = generator.CreateNavigator();
				this.context = context;

				displayName = this.generator.GetAttribute("type", "");
			}
			#endregion

			#region Methods
			public override bool ShouldSerializeValue(object component)
			{
				return false;
			}

			public override bool CanResetValue(object component)
			{
				return false;
			}

			public override void ResetValue(object component)
			{
				throw new NotSupportedException();
			}

			public override object GetValue(object component)
			{
				return generator.GetAttribute("assembly", "");
			}

			public override void SetValue(object component, object value)
			{
				throw new NotSupportedException();
			}
			#endregion
		}
		#endregion
	}
}
